package com.hzqy.web.interceptor;

import java.io.PrintWriter;
import java.util.Base64;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.hzqy.commons.utils.HttpGetData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.hzqy.commons.utils.ConstantUtils;
import com.hzqy.service.system.SysProcessLogsServiceBeen;
import com.hzqy.web.vo.PmsUserVo;
import com.hzqy.web.vo.SysProcessLogsVo;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class PmsInterceptor implements HandlerInterceptor {
	protected final Logger LOG = LoggerFactory.getLogger(getClass());
	@Resource
	private SysProcessLogsServiceBeen sysProcessLogsServiceBeen;

	private static Pattern sqlInjectRegexPattern = Pattern.compile("\\b(and|exec|insert|select|drop|grant|alter|delete|update|count|chr|mid|master|truncate|char|declare|or)\\b|(\\*|;|\\+|'|%)");

	public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
//		if (checkAttack(request)) {
//			response.setCharacterEncoding("UTF-8");
//			response.setContentType("application/json;charset=UTF-8");
//			PrintWriter pw = response.getWriter();
//			pw.write("{ message: '参数输入存在敏感信息，请检查' }");
//			pw.flush();
//			pw.close();
//			return false;
//		}
		boolean flag=true;
		String uri=request.getRequestURI();
		String ip=HttpGetData.getIpAddr(request);
		String str=uri.substring(uri.lastIndexOf("/")+1,uri.indexOf(".do")+3);
		if(str.startsWith("insert")||str.startsWith("update")||str.startsWith("del")||str.endsWith("login.do")||str.endsWith("loginOut.do")){//过滤请求不做记录
				String f_pa_url=uri.substring(uri.lastIndexOf("/")+1,uri.indexOf(".do")+3);
				PmsUserVo puv = (PmsUserVo) request.getSession().getAttribute(ConstantUtils.SESSION_USER);
				String processLogsName=sysProcessLogsServiceBeen.selectProcessName(f_pa_url);
				HashMap<String, String> hashMap = new HashMap<String,String>();
				SysProcessLogsVo sysProcessLogsVo=new SysProcessLogsVo();
				String logId="";
				String beforeparaneters="";
				String afterparaneters="";
				Map<String,String[]> map = request.getParameterMap();
				if (str.startsWith("update")) { //判断是否是修改
					if("updateUserPwd.do".equals(str)||"updateUserStatus.do".equals(str)||"updateUserPhone.do".equals(str)){

					}else{
						HttpSession session = request.getSession();
						hashMap=(HashMap<String, String>) session.getAttribute(puv.getF_pu_name()); //根据用户获取map数据
						HashMap<String, String> beforeHashMap = new HashMap<String,String>();
						if (hashMap!=null) {
							for(Entry<String, String> me : hashMap.entrySet()){
								String name = me.getKey();
								String v = String.valueOf(me.getValue());
								beforeHashMap.put(name, v);
							}
						}
						try{
							logId=hashMap.get("logId");
						}catch (Exception e) {
							LOG.error("不存在操作页面ID" + e);
						}
						for(Entry<String, String[]> me : map.entrySet()){
							String name = me.getKey();
							if ("stime".equals(name) || "sign".equals(name) || "pictureId".equals(name)
									||"picRelationValue".equals(name) || "picIdValue".equals(name)) { //key值不处理
								continue;
							}
							String [] v = me.getValue();
							if(name != null && (name.indexOf("pwd") >= 0 || name.indexOf("password") >= 0)) {
								if (hashMap==null) {
									afterparaneters+=name+":"+"*"+"<br>";
								} else {
									if (!v[0].equals(hashMap.get(name))) {
										beforeparaneters+=name+":"+"*"+"<br>";
										afterparaneters+=name+":"+"*"+"<br>";
									}
								}
							} else {
								String v0=""; //遍历获取所有value值
								for(int i=0; i<v.length; i++) {
									if (i+1 == v.length) {
										v0+=v[i];
									} else {
										v0+=v[i]+",";
									}
								}
								if ("f_cc_desc".equals(name)) { //解码
									try{
										Base64.Decoder decoder = Base64.getDecoder();
										byte[] bytes = decoder.decode(v0);
										v0 = new String(bytes, "UTF-8");
									} catch (Exception e) {
										LOG.debug("f_cc_desc不需要解码base64"+e);
									}
								}
								if (hashMap==null) {
									afterparaneters+=name+":"+v0+"<br>";
								} else {
									if (!v0.equals(String.valueOf(hashMap.get(name)))) {
										if (String.valueOf(hashMap.get(name)).equals("null")) {
											beforeparaneters+=name+": <br>";
										} else {
											beforeparaneters+=name+":"+String.valueOf(hashMap.get(name))+"<br>";
										}
										afterparaneters+=name+":"+v0+"<br>";
									}
									beforeHashMap.remove(name);
								}
							}
						}
						if(str.equals("update_group_schedules.do")) {
							for(Entry<String, String> me : beforeHashMap.entrySet()){
								String name = me.getKey();
								if(!name.equals("logId")) {
									String v = String.valueOf(me.getValue());
									beforeparaneters+=name+":"+v+"<br>";
								}
							}
						}
						//session.removeAttribute(puv.getF_pu_name()); //清空此用户map
					}
				} else if (str.startsWith("del")){
					for(Entry<String, String[]> me : map.entrySet()){
						String name = me.getKey();
						if(name.endsWith("id") || name.endsWith("ids")) {
							String [] v = me.getValue();
							logId+=name+":"+v[0]+"<br>";
						}
					}
				} else {
					for(Entry<String, String[]> me : map.entrySet()){
						String name = me.getKey();
						if ("stime".equals(name) || "sign".equals(name)) { //key值不处理
							continue;
						}
						String [] v = me.getValue();
						if(v[0]!=null&&!v[0].equals("")){
							if(name != null && (name.indexOf("pwd") >= 0 || name.indexOf("password") >= 0)) {
								afterparaneters+=name+":"+"*"+"<br>";
							} else {
								afterparaneters+=name+":"+v[0]+"<br>";
							}
						}
					}
				}
				if(beforeparaneters.length()>1000){
					beforeparaneters=beforeparaneters.substring(0, 1000);
				}
				//afterparaneters=((afterparaneters.lastIndexOf(",")>=0)?afterparaneters.substring(0,afterparaneters.length()-1):afterparaneters);
				if(afterparaneters.length()>1000){
					afterparaneters=afterparaneters.substring(0, 1000);
				}
				if(puv!=null){
					if(uri.endsWith("login.do")&&afterparaneters.equals("")){//登入后刷新不记录
						return flag;
					}else{
						sysProcessLogsVo.setF_spl_username(puv.getF_pu_name());
						sysProcessLogsVo.setF_spl_userid(puv.getF_pu_id());
						sysProcessLogsVo.setF_spl_name(processLogsName==null?"用户登入或其他操作":processLogsName);
						sysProcessLogsVo.setF_spl_url(uri);
						sysProcessLogsVo.setF_spl_requestip(ip);
						sysProcessLogsVo.setF_spl_operateid(logId);
						sysProcessLogsVo.setF_spl_before(beforeparaneters);
						sysProcessLogsVo.setF_spl_after(afterparaneters);
					}
				}else{//无用户信息时执行一下代码
					if(uri.endsWith("login.do")){//初始登入无session
						String userName=request.getParameter("f_pu_name");
						if(userName==null){//不记录未登入刷新
							return flag;
						}
						sysProcessLogsVo.setF_spl_username(userName);
						sysProcessLogsVo.setF_spl_userid(0);
						sysProcessLogsVo.setF_spl_name("用户登入");
						sysProcessLogsVo.setF_spl_url(uri);
						sysProcessLogsVo.setF_spl_requestip(ip);
						sysProcessLogsVo.setF_spl_before(beforeparaneters);
						sysProcessLogsVo.setF_spl_after(afterparaneters);
					}else{//无用户信息请求
						sysProcessLogsVo.setF_spl_username("未知用户");
						sysProcessLogsVo.setF_spl_userid(0);
						sysProcessLogsVo.setF_spl_name(processLogsName==null?"用户退出或其他操作":processLogsName);
						sysProcessLogsVo.setF_spl_url(uri);
						sysProcessLogsVo.setF_spl_requestip(ip);
						sysProcessLogsVo.setF_spl_before(beforeparaneters);
						sysProcessLogsVo.setF_spl_after(afterparaneters);
					}
				}
				sysProcessLogsServiceBeen.insertProcessLogs(sysProcessLogsVo);
		}else{
			flag=true;
		}
		return flag;
	}
	/**
	 * 管理平台拦截器，用于记录用户操作记录
	 */
	public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {

	}

	public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
	}

	private boolean checkAttack(HttpServletRequest request) {
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			String[] values = request.getParameterValues(name);
			for (int i = 0; i < values.length; i++) {
				if (checkSqlInject(values[i])) {
					return true;
				}
			}
		}
		return false;
	}

	// 存在攻击，则返回true
	private static boolean checkSqlInject(String value) {
		if (value == null || "".equals(value.trim())) {
			return false;
		}

		Matcher matcher = sqlInjectRegexPattern.matcher(value.toLowerCase());
		return matcher.find();
	}

}
